package net.luohuasheng.bee.proxy.mybatis.executor.processor;

import net.luohuasheng.bee.jdbc.tools.common.utils.CollectionUtils;
import net.luohuasheng.bee.proxy.core.utils.CastUtils;
import net.luohuasheng.bee.proxy.core.utils.StringUtils;
import net.luohuasheng.bee.proxy.mybatis.common.utils.MapperUtils;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.session.Configuration;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static net.luohuasheng.bee.proxy.mybatis.executor.intercetor.BaseInterceptor.Index.MAPPED_STATEMENT_INDEX;
import static net.luohuasheng.bee.proxy.mybatis.executor.intercetor.BaseInterceptor.LANGUAGE_DRIVER;

/**
 * @author luohuasheng
 */
public class UpdateByIdProcessor extends BaseProcessor {

    public static final String UPDATE_COLS = "updateById";

    public UpdateByIdProcessor(Configuration configuration, Class<?> entityClass) {
        super(configuration, entityClass);
    }

    @Override
    public void rewrite(Invocation invocation, MappedStatement ms, BoundSql boundSql, Object parameter) {
        List<String> fields = BaseProcessor.getUpdateExpressionFields();
        String sql = boundSql.getSql();
        Map<String, Object> data = CastUtils.cast(((Map<?, ?>) parameter).get("data"));
        sql = sql.replace(UpdateByIdProcessor.UPDATE_COLS, StringUtils.join(data.keySet().stream().map(o -> (!CollectionUtils.isEmpty(fields) && fields.contains(o)) ? o + "=" + data.getOrDefault(o, "null") : o + "=#{data." + o + "}").collect(Collectors.toList()), ","));
        SqlSource sqlSource = LANGUAGE_DRIVER.createSqlSource(ms.getConfiguration(), "<script>\n\t" + sql + "</script>", null);
        BoundSql newBoundSql = sqlSource.getBoundSql(parameter);
        newBoundSql.getParameterMappings().addAll( boundSql.getParameterMappings());
        invocation.getArgs()[MAPPED_STATEMENT_INDEX.getAnInt()] = MapperUtils.copyFromNewSql(ms, newBoundSql);
    }

    @Override
    public SqlSource createSqlSource() {
        return createSqlSource("UPDATE " + jpaTableDto.getName() + " SET " + UPDATE_COLS + " " + addLogicConditions(jpaTableDto.getColumns()) + createPkSql(jpaTableDto.getColumns()));
    }


}
